﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace Simple.Common.Cache
{
    //https://www.cnblogs.com/peterzhang123/p/12310384.html
    //https://blog.csdn.net/wangzhenxing991026/article/details/108717928?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_v2~rank_aggregation-3-108717928.pc_agg_rank_aggregation&utm_term=redis%E7%BC%93%E5%AD%98%E5%95%86%E5%93%81%E5%88%97%E8%A1%A8&spm=1000.2123.3001.4430
    public interface IRedisService
    {
        #region string
        ///// <summary>
        ///// 设置缓存（无失效时间）。
        ///// </summary>
        ///// <param name="key">键。</param>
        ///// <param name="value">值。</param>
        ///// <returns></returns>
        //Task<bool> SetAsync(string key, object value, bool? isExpire = false);

        /// <summary>
        /// 设置缓存（有效期）。
        /// </summary>
        /// <param name="key">键。</param>
        /// <param name="value">值。</param>
        /// <param name="expireTimeSpan"></param>
        /// <param name="isExpire"></param>
        /// <returns></returns>
        Task<bool> SetAsync(string key, object value, TimeSpan? expireTimeSpan=null, bool? isExpire = false);


        /// <summary>
        /// 指定键是否存在。
        /// </summary>
        /// <param name="key">键。</param>
        /// <returns></returns>
        Task<bool> IsExsitsAsync(string key);

        /// <summary>
        /// 设置缓存过期时间（有限时间）。
        /// </summary>
        /// <param name="key">键。</param>
        /// <param name="expireTimeSpan">有效期。</param>
        /// <returns></returns>
        Task<bool> ExpireAsync(string key, TimeSpan? expireTimeSpan=null);


        /// <summary>
        /// 获取字符串缓存。
        /// </summary>
        /// <param name="key">键。</param>
        /// <returns></returns>
        Task<string> GetAsync(string key);

        /// <summary>
        /// 获取缓存（泛型）。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="key">键。</param>
        /// <returns></returns>
        Task<T> GetAsync<T>(string key);

        /// <summary>
        /// 清除指定缓存。
        /// </summary>
        /// <param name="key">键。</param>
        /// <returns></returns>
        Task RemoveAsync(string key);

        /// <summary>
        /// 批量清除缓存。
        /// </summary>
        /// <param name="keys">键集合。</param>
        /// <returns></returns>
        Task RemoveAsync(IEnumerable<string> keys);
        #endregion

        #region hash
        /// <summary>
        /// 判断该字段是否存在 hash 中
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<bool> HashExistsAsync(string key, string hashField);

        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<bool> HashDeleteAsync(string redisKey, string hashField);

        /// <summary>
        /// 从 hash 中移除多个指定字段
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<long> HashDeleteAsync(string redisKey, IEnumerable<RedisValue> hashField);

        /// <summary>
        /// 在 hash 中保存或修改一个值   字符类型
        /// set or update the HashValue for string key 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <param name="expireTimeSpan">过期时间,可空</param>
        /// <returns></returns>
        Task<bool> HashSetAsync(string key, string hashField, string value, TimeSpan? expireTimeSpan = null);

        /// <summary>
        /// 保存一个字符串类型集合  
        /// </summary>
        /// <param name="key">Redis Key</param>
        /// <param name="list">数据集合</param>
        /// <param name="getFiledKey">字段key</param>
        /// <param name="expireTimeSpan"></param>
        Task<bool> HashSetListAsync(string key, IEnumerable<string> list, Func<string, string> getFiledKey,
            TimeSpan? expireTimeSpan = null);
        #endregion

        /// <summary>
        /// 清空缓存。
        /// </summary>
        /// <returns></returns>
        Task ClearAsync(string param);

        /// <summary>
        /// 加锁。
        /// </summary>
        /// <param name="key">键。</param>
        /// <param name="timeSpan">锁定时间（默认：10s）。</param>
        Task<bool> TryEnterLockAsync(string key, TimeSpan? timeSpan = null);

        /// <summary>
        /// 释放锁。
        /// </summary>
        /// <param name="key">键。</param>
        Task ExitLockAsync(string key);

        /// <summary>
        /// 获取分布式锁并执行Action（超时会自动释放）
        /// </summary>
        /// <param name="lockKey">锁key</param>
        /// <param name="func">执行方法</param>
        /// <param name="timeSpan">自动释放时间，默认10秒</param>
        /// <returns></returns>
        Task<bool> LockAndRun(string lockKey, Func<Task> func, TimeSpan? timeSpan = null);

        /// <summary>
        /// 获取分布式锁并执行Action（超时会自动释放）
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="lockKey">锁key</param>
        /// <param name="func">执行方法</param>
        /// <param name="errorMsg">未取得锁时异常消息</param>
        /// <param name="timeSpan">自动释放时间，默认10秒</param>
        /// <returns></returns>
        Task<T> LockAndRun<T>(string lockKey, Func<Task<T>> func, string errorMsg, TimeSpan? timeSpan = null);
    }
}